package com.aipanda.entity;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.time.DateUtils;

import com.aipanda.pojo.Setting;
import com.aipanda.util.SettingUtils;

/**
 * 购物车类
 * @author wanyuxiang
 *
 */
@Entity
@Table(name = "aipanda_cart")
public class Cart extends BaseEntity {
	private static final long serialVersionUID = -6565967051825794561L;
	public static final int TIMEOUT = 604800;
	public static final Integer MAX_PRODUCT_COUNT = 100;
	public static final String ID_COOKIE_NAME = "cartId";
	public static final String KEY_COOKIE_NAME = "cartKey";
	private String key;
	private Member member;
	private Set<CartItem> cartItems = new HashSet<CartItem>();
	
	class CartPredicate implements Predicate {
		@SuppressWarnings("unused")
		private Cart cart;
		private GiftItem giftItem;
		
		public CartPredicate(Cart cart, GiftItem giftItem) {
			super();
			this.cart = cart;
			this.giftItem = giftItem;
		}



		public boolean evaluate(Object object) {
			GiftItem localGiftItem = (GiftItem) object;
			return localGiftItem != null&& (localGiftItem.getGift().equals(this.giftItem.getGift()));
		}
	}
	
	@Column(name = "cart_key", nullable = false, updatable = false)
	public String getKey() {
		return this.key;
	}

	public void setKey(String key) {
		this.key = key;
	}

	@OneToOne(fetch = FetchType.LAZY)
	@JoinColumn(name="member")
	public Member getMember() {
		return this.member;
	}

	public void setMember(Member member) {
		this.member = member;
	}

	@OneToMany(mappedBy = "cart", fetch = FetchType.LAZY, cascade = {CascadeType.REMOVE })//orphanRemoval=true等值CascadeType.REMOVE
	public Set<CartItem> getCartItems() {
		return this.cartItems;
	}

	public void setCartItems(Set<CartItem> cartItems) {
		this.cartItems = cartItems;
	}

	/**
	 * 获得购物车里面所有产品的积分数
	 * @return
	 */
	@Transient
	public int getTotalPoint() {
		int totalPoint = 0;
		//获得购物车所有产品对应的积分值
		if (getCartItems() != null) {
			Iterator<CartItem> cartItems = getCartItems().iterator();
			while (cartItems.hasNext()) {
				CartItem cartItem = cartItems.next();
				if (cartItem == null){
					continue;
				}
				totalPoint = totalPoint + (int) cartItem.getPoint();
			}
		}
		
		//计算有效的促销类型之后的积分数
		Iterator<Promotion> promotions = getCartItemVaildPromotions().iterator();
		while (promotions.hasNext()) {
			Promotion promotion = promotions.next();
			totalPoint = promotion.calculatePromotionAfterPoint(totalPoint);
		}
		return totalPoint;
	}

	@Transient
	public int getWeight() {
		int i = 0;
		if (getCartItems() != null) {
			Iterator<CartItem> cartItems = getCartItems().iterator();
			while (cartItems.hasNext()) {
				CartItem localCartItem = cartItems.next();
				if (localCartItem == null)
					continue;
				i += localCartItem.getWeight();
			}
		}
		return i;
	}

	@Transient
	public int getQuantity() {
		int i = 0;
		if (getCartItems() != null) {
			Iterator<CartItem> localIterator = getCartItems().iterator();
			while (localIterator.hasNext()) {
				CartItem localCartItem = localIterator.next();
				if ((localCartItem == null)
						|| (localCartItem.getQuantity() == null))
					continue;
				i += localCartItem.getQuantity().intValue();
			}
		}
		return i;
	}

	/**
	 * 获得购物车所有产品的总金额
	 * @return
	 */
	@Transient
	public BigDecimal getTotalPrice() {
		BigDecimal bigDecimal = new BigDecimal(0);
		if (getCartItems() != null) {
			Iterator<CartItem> iterator = getCartItems().iterator();
			while (iterator.hasNext()) {
				CartItem cartItem = iterator.next();
				if (cartItem == null|| cartItem.getSubtotal() == null){
					continue;
				}
				bigDecimal = bigDecimal.add(cartItem.getSubtotal());
			}
		}
		return bigDecimal;
	}

	/**
	 * 如果购买产品有促销活动，获得促销总金额
	 * @return  返回促销后的总金额
	 */
	@Transient
	public BigDecimal getPromotionTotalAmount() {
		Setting setting = SettingUtils.get();
		BigDecimal totalAmount = getTotalPrice();
		Iterator<Promotion> iterator = getCartItemVaildPromotions().iterator();
		while (iterator.hasNext()) {
			Promotion promotion = iterator.next();
			totalAmount = promotion.calculatePromotionAfterAmount(totalAmount);
		}
		return setting.setPriceScale(totalAmount);
	}

	/**
	 * 获得优惠金额
	 * @return 优惠金额
	 */
	@Transient
	public BigDecimal getDiscount() {
		//优惠金额=总金额-促销后的总金额
		BigDecimal bigDecimal = getTotalPrice().subtract(getPromotionTotalAmount());
		return bigDecimal.compareTo(new BigDecimal(0)) > 0 ? bigDecimal: new BigDecimal(0);
	}

	@Transient
  public Set<GiftItem> getGiftItems()
  {
    Set<GiftItem> set = new HashSet<GiftItem>();
    Iterator<Promotion> promotions = getCartItemVaildPromotions().iterator();
    while (promotions.hasNext())
    {
      Promotion localPromotion = promotions.next();
      if (localPromotion.getGiftItems() == null)
        continue;
      Iterator<GiftItem> giftItems = localPromotion.getGiftItems().iterator();
      while (giftItems.hasNext())
      {
        GiftItem giftItem = giftItems.next();
        GiftItem newGiftItem = (GiftItem)CollectionUtils.find(set, new CartPredicate(this, giftItem));
        if (newGiftItem != null)
          newGiftItem.setQuantity(Integer.valueOf(newGiftItem.getQuantity().intValue() + giftItem.getQuantity().intValue()));
        else
          set.add(giftItem);
      }
    }
    return set;
  }
	
	/**
	 * 获得购物车所有产品有效的促销类型
	 * @return  有效的促销类型
	 */
	@Transient
	public Set<Promotion> getCartItemVaildPromotions() {
		Set<Promotion>  productAllPromotions = new HashSet<Promotion>();
		if (getCartItems() != null) {
			Iterator<CartItem>	cartItems = getCartItems().iterator();
			while (cartItems.hasNext()) {
				CartItem cartItem = cartItems.next();
				if (cartItem == null|| cartItem.getProduct() == null){
					continue;
				}
				productAllPromotions.addAll(cartItem.getProduct().getValidPromotions());//获得购物车所有产品对应有效的促销类型
			}
		}
		
		Set<Promotion> qualifiedPromotions = new TreeSet<Promotion>();//有效促销类型的集合
		Iterator<Promotion> promotions = productAllPromotions.iterator();
		while (promotions.hasNext()) {
			Promotion	promotion = promotions.next();
			if (!decideVaildPromotion(promotion)){
				continue;
			}
			 qualifiedPromotions.add(promotion);
		}
		return  qualifiedPromotions;
	}

	/**
	 * 判断是否是有效的产品促销
	 * @param promotion  产品的促销类型
	 * @return  有效true/无效false
	 */
	@Transient
	private boolean decideVaildPromotion(Promotion promotion) {
		//产品是否在有效的开始时候和介绍时间之内
		if (promotion == null || !promotion.hasBegun()|| promotion.hasEnded()){
			return false;
		}
		//促销对应的会员等级是否为null&&会员为NUll&&会员对应的会员等级是否为NULL&&会员等级是否包含了当前会员对应的等级
		if (promotion.getMemberRanks() == null|| getMember() == null|| getMember().getMemberRank() == null
				|| !promotion.getMemberRanks().contains(getMember().getMemberRank())){
			return false;
		}
		BigDecimal bigDecimal = new BigDecimal(0);
		if (getCartItems() != null) {
			//又获得购物车对应的商品类集合并进行迭代
			Iterator<CartItem> cartItems = getCartItems().iterator();
			while (cartItems.hasNext()) {
				CartItem cartItem = cartItems.next();
				if (cartItem == null){
					continue;
				}
				Product product = cartItem.getProduct();
				if (product == null){
					continue;
				}
				//判断产品是否是允许参与促销类型包含形参传递的类型
				if (product.getPromotions() != null&& product.getPromotions().contains(promotion)) {
					bigDecimal = bigDecimal.add(cartItem.getSubtotal());
					//判断产品对应的商品分类是否允许参加促销类型包含形参传递的类型
				} else if (product.getProductCategory() != null&& product.getProductCategory().getPromotions().contains(promotion)) {
					bigDecimal = bigDecimal.add(cartItem.getSubtotal());
				} else {
					//判断品牌对应的商品分类是否允许参加促销类型包含形参传递的类型
					if (product.getBrand() == null|| !product.getBrand().getPromotions().contains(promotion)){
						continue;
					}
					bigDecimal = bigDecimal.add(cartItem.getSubtotal());
				}
			}
		}
		return (promotion.getStartPrice() == null || promotion.getStartPrice().compareTo(bigDecimal) <= 0)
				&& (promotion.getEndPrice() == null || promotion.getEndPrice().compareTo(bigDecimal) >= 0);
	}

	@Transient
	public boolean isValid(Coupon coupon) {
		if (coupon == null || !coupon.getIsEnabled().booleanValue()|| !coupon.hasBegun() || coupon.hasExpired())
			return false;
		return (coupon.getStartPrice() == null || coupon.getStartPrice().compareTo(getPromotionTotalAmount()) <= 0)
				&& (coupon.getEndPrice() == null || coupon.getEndPrice().compareTo(getPromotionTotalAmount()) >= 0);
	}

	@Transient
	public CartItem getCartItem(Product product) {
		if ((product != null) && (getCartItems() != null)) {
			Iterator<CartItem> cartItems = getCartItems().iterator();
			while (cartItems.hasNext()) {
				CartItem localCartItem = cartItems.next();
				if (localCartItem != null&& localCartItem.getProduct() == product)
					return localCartItem;
			}
		}
		return null;
	}

	@Transient
	public boolean contains(Product product) {
		if ((product != null) && (getCartItems() != null)) {
			Iterator<CartItem> localIterator = getCartItems().iterator();
			while (localIterator.hasNext()) {
				CartItem localCartItem = localIterator.next();
				if ((localCartItem != null)
						&& (localCartItem.getProduct() == product))
					return true;
			}
		}
		return false;
	}

	@Transient
	public String getToken() {
		HashCodeBuilder localHashCodeBuilder = new HashCodeBuilder(17, 37)
				.append(getKey());
		if (getCartItems() != null) {
			Iterator<CartItem> localIterator = getCartItems().iterator();
			while (localIterator.hasNext()) {
				CartItem localCartItem = localIterator.next();
				localHashCodeBuilder.append(localCartItem.getProduct()).append(localCartItem.getQuantity()).append(localCartItem.getUnitPrice());
			}
		}
		return DigestUtils.md5Hex(localHashCodeBuilder.toString());
	}
	
	/**
	 * 判断是否库存不足
	 * @return
	 */
	
	@Transient
	public boolean getIsLowStock() {
		if (getCartItems() != null) {
			Iterator<CartItem> cartItems = getCartItems().iterator();
			while (cartItems.hasNext()) {
				CartItem cartItem = cartItems.next();
				if (cartItem != null && cartItem.getIsLowStock()){
					return true;
				}
			}
		}
		return false;
	}

	@Transient
	public boolean hasExpired() {
		return new Date().after(DateUtils.addSeconds(getModifyDate(), 604800));
	}

	/**
	 * 是否允许优惠券
	 * @return
	 */
	@Transient
	public boolean isCouponAllowed() {
		Iterator<Promotion> promotions = getCartItemVaildPromotions().iterator();
		while (promotions.hasNext()) {
			Promotion promotion = promotions.next();
			if (promotion != null && !promotion.getIsCouponAllowed()){
				return false;
			}
		}
		return true;
	}

	@Transient
	public boolean isEmpty() {
		return getCartItems() == null || getCartItems().isEmpty();
	}
}
